﻿/*------------------------------------------------------------------------

MATRIX.HPP v1.1.4

Copyright 楊志賢 CxxlMan, 2012 - 2014
All Rights Reserved

------------------------------------------------------------------------*/

#if !defined(__MATRIX_HPP_Cxxl3D)
#define __MATRIX_HPP_Cxxl3D

#include <CRITICAL.HPP>
#include <CXXL3DCOMMON.HPP>
#include "VECTOR.HPP"

namespace Cxxl3D
{

struct C3DVector4;
class Vector4;
class Matrix4x4;

// 產生繞指定向量旋轉的矩陣
inline Matrix4x4 cxxlFASTCALL Rotate(const Vector4 &v, const C3D_FLOAT fSin, const C3D_FLOAT fCos);

// 向量 * 矩陣
inline C3DVector4 cxxlFASTCALL operator*(const C3DVector4 &v, const Matrix4x4 &m);

// 矩陣 * 矩陣
inline Matrix4x4 cxxlFASTCALL operator*(const Matrix4x4 &m1, const Matrix4x4 &m2);

// 座標轉換矩陣的反矩陣函數
inline Matrix4x4 cxxlFASTCALL CoordinateInvert(const Matrix4x4 &m);


struct C3DMatrix4x4
{
 	union
	{
		struct
		{
      C3D_FLOAT m_00, m_01, m_02, m_03;
      C3D_FLOAT m_10, m_11, m_12, m_13;
      C3D_FLOAT m_20, m_21, m_22, m_23;
      C3D_FLOAT m_30, m_31, m_32, m_33;
		};

		struct
		{
			C3DVector4 m_Vec0, m_Vec1, m_Vec2, m_Vec3;
		};
	};
};


// 單位矩陣，
//extern Matrix4x4 g_Matrix4x4_Identity;

class Matrix4x4:private C3DMatrix4x4
{
  // CxxlMan::CriticalSec csObject;

public:

/*
  void cxxlFASTCALL Lock()
  {
    csObject.Enter();
  }

  void cxxlFASTCALL UnLock()
  {
    csObject.Leave();
  }
*/

public:

  // Constructor
  Matrix4x4()
  {
    
  }

  // Constructor
  Matrix4x4(const C3DVector4 &v0, const C3DVector4 &v1, const C3DVector4 &v2, const C3DVector4 &v3)
  {
    m_Vec0 = v0;
    m_Vec1 = v1;
    m_Vec2 = v2;
    m_Vec3 = v3;
  }

  // Constructor
  Matrix4x4(
		C3D_FLOAT f00, C3D_FLOAT f01, C3D_FLOAT f02, C3D_FLOAT f03,
		C3D_FLOAT f10, C3D_FLOAT f11, C3D_FLOAT f12, C3D_FLOAT f13,
		C3D_FLOAT f20, C3D_FLOAT f21, C3D_FLOAT f22, C3D_FLOAT f23,
		C3D_FLOAT f30, C3D_FLOAT f31, C3D_FLOAT f32, C3D_FLOAT f33
	)	
	{
		m_00 = f00; m_01 = f01; m_02 = f02; m_03 = f03;
		m_10 = f10; m_11 = f11; m_12 = f12; m_13 = f13;
		m_20 = f20; m_21 = f21; m_22 = f22; m_23 = f23;
		m_30 = f30; m_31 = f31; m_32 = f32; m_33 = f33;
	}


  // Copy Constructor
  Matrix4x4(const	Matrix4x4 &Matrix4x4_Arg)	
	{
    // Matrix4x4_Arg.csObject.Enter();
    *(C3DMatrix4x4*)this = (const C3DMatrix4x4&)Matrix4x4_Arg;
    // Matrix4x4_Arg.csObject.Leave();
	}


  // Copy
  Matrix4x4 & cxxlFASTCALL operator=(const Matrix4x4 &Matrix4x4_Arg)
  {
/*
    Matrix4x4 tmp(Matrix4x4_Arg); // 在 Copy Constructor 有同步控制
    
    csObject.Enter();
    *(C3DMatrix4x4*)this = (C3DMatrix4x4)tmp;
    csObject.Leave();
*/
    *(C3DMatrix4x4*)this = (const C3DMatrix4x4&)Matrix4x4_Arg;
    return *this;
  }

  // 複製 C3DMatrix4x4
  C3DMatrix4x4 cxxlFASTCALL Get_C3DMatrix4x4() const
  {
    return *(C3DMatrix4x4 *)this;
  }

  // 轉形
  // 適用於 const
  cxxlFASTCALL operator const C3DMatrix4x4&() const
  {
    return *(const C3DMatrix4x4 *)this;
  }

  // 轉形
  cxxlFASTCALL operator C3DMatrix4x4&()
  {
    return *(C3DMatrix4x4 *)this;
  }


  // 化為單位矩陣
	void cxxlFASTCALL Identity()
	{
    //csObject.Enter();
    m_00 = 1.0f; m_01 = 0.0f; m_02 = 0.0f; m_03 = 0.0f;
    m_10 = 0.0f; m_11 = 1.0f; m_12 = 0.0f; m_13 = 0.0f;
    m_20 = 0.0f; m_21 = 0.0f; m_22 = 1.0f; m_23 = 0.0f;
    m_30 = 0.0f; m_31 = 0.0f; m_32 = 0.0f; m_33 = 1.0f;
    //csObject.Leave();
	}

  // 設定指定的橫行
 	void cxxlFASTCALL SetRow(int row, const Vector4 &vec)
	{
//		assert(row>=0 && row<4);
    //csObject.Enter();
		C3DVector4 *rows = &m_Vec0;
		rows[row] = vec;
    //csObject.Leave();
	}

  // 設定指定的縱列
	void cxxlFASTCALL SetColumn(int column, const Vector4 &vec)
	{
//		assert(column>=0 && column<4);
    //csObject.Enter();
    C3D_FLOAT *p = &m_00 + column;
		p[0] = vec.GetX(); 
		p[4] = vec.GetY(); 
		p[8] = vec.GetZ(); 
		p[12] = vec.GetW();
    //csObject.Leave();
	}

  // 取得指定的橫行
	const C3DVector4 cxxlFASTCALL GetRow(int row) const
	{
//		assert(row>=0 && row<4);
    //CxxlMan::CriticalSecHandle AutoCSH(csObject);

		const C3DVector4 *rows = &m_Vec0;
		return rows[row];
	}

  // 取得指定的縱列
	const C3DVector4 cxxlFASTCALL GetColumn(int column) const
	{
//		assert(column>=0 && column<4);
//    CxxlMan::CriticalSecHandle AutoCSH(csObject);
		Vector4 vec;
		const C3D_FLOAT *p = &m_00 + column;

		vec.SetX(p[0]);
		vec.SetY(p[4]);
		vec.SetZ(p[8]);
		vec.SetW(p[12]);

		return vec;
	}

	C3DVector4 & cxxlFASTCALL operator[](int row)
  {
    C3DVector4 *rows = &m_Vec0;
    return rows[row];
  }


  // 取得單位矩陣
  static Matrix4x4 cxxlFASTCALL IdentityCreate()
  {
    static Matrix4x4 r(
      1.0, 0.0, 0.0, 0.0,
      0.0, 1.0, 0.0, 0.0,
      0.0, 0.0, 1.0, 0.0,
      0.0, 0.0, 0.0, 1.0      
    );
    return r;
  }



  void *operator new(size_t s)
  {
    return AllocateAlignedMemory(s);
  }

  void operator delete(void *m,size_t s) 
  {
    ReleaseAlignedMemory(m);
  }

  void *operator new [](size_t s)
  {
    return AllocateAlignedMemory(s);
  }

  void operator delete [](void *m,size_t s) 
  {
    ReleaseAlignedMemory(m);
  }




  // 產生繞指定向量旋轉的矩陣
  friend inline Matrix4x4 cxxlFASTCALL Rotate(const Vector4 &v, const C3D_FLOAT fSin, const C3D_FLOAT fCos);

  // 向量 * 矩陣
  friend inline C3DVector4 cxxlFASTCALL operator*(const C3DVector4 &v, const Matrix4x4 &m);

  // 矩陣 * 矩陣
  friend inline Matrix4x4 cxxlFASTCALL operator*(const Matrix4x4 &m1, const Matrix4x4 &m2);

  // 座標轉換矩陣的反矩陣函數
  friend inline Matrix4x4 cxxlFASTCALL CoordinateInvert(const Matrix4x4 &m);

};




}   /* namespace Cxxl3D */
#endif
